package yagwl.client.widget;

import java.util.logging.Logger;

import yagwl.client.model.ItemListCache;
import yagwl.client.model.DataReadyEventBus;
import yagwl.client.model.ItemDTO;
import yagwl.client.model.ItemListEvent;
import yagwl.client.model.ItemListEvent.ItemListEventHandler;
import yagwl.client.resource.CellTableResources;
import yagwl.client.widget.internal.ButtonBar;
import yagwl.client.widget.internal.PageSizer;
import yagwl.client.widget.internal.Sorter;

import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Builds on CellTable, SimplePager and adds sorting options, page size options
 * and table-level action buttons
 */
public class PagedCellTable extends Composite implements ItemListEventHandler {
  private static final Logger log = Logger.getLogger(PagedCellTable.class
      .getName());
  private final VerticalPanel rootVP = new VerticalPanel();
  private final CellTable<ItemDTO> cellTable = new CellTable<ItemDTO>(15,
      CellTableResources.R);
  private final SimplePager pager = new MySimplePager();
  private final SimplePager pager2 = new MySimplePager();
  private final PageSizer pageSizer = new PageSizer();
  private ButtonBar buttonBar;
  private Sorter sorter;
  private ItemListCache listCache;

  public PagedCellTable() {
    initWidget(rootVP);
    // register self as a listener of data ready events
    DataReadyEventBus.getInstance().addHandler(ItemListEvent.TYPE, this);
  }

  public void setListCache(ItemListCache listCache) {
    this.listCache = listCache;
    if (sorter != null)
      listCache.setSortOrderNumber(sorter.getSortOrderNumber());
    listCache.fetchNext();
    renderUI();
  }

  private void renderUI() {
    // top
    HorizontalPanel tophp = new HorizontalPanel();
    tophp.setWidth("100%");
    // top left
    if (buttonBar != null) {
      tophp.add(buttonBar);
      buttonBar.renderUI();
    }
    // top right
    HorizontalPanel navhp = new HorizontalPanel();
    if (sorter != null && sorter.isRenderable()) {
      sorter.renderUI(new Sorter.SortOrderChangeHandler() {
        @Override
        public void onChange() {
          listCache.setSortOrderNumber(sorter.getSortOrderNumber());
          pager.startLoading();
          listCache.fetchNext();
        }
      });
      navhp.add(sorter);
      navhp.setCellVerticalAlignment(sorter, HasVerticalAlignment.ALIGN_MIDDLE);
      navhp.add(new Spacer(20, 1));
    }
    if (pageSizer != null && pageSizer.isRenderable()) {
      pageSizer.renderUI(new PageSizer.PageSizeChangeHandler() {
        @Override
        public void onChange() {
          cellTable.setPageSize(pageSizer.getPageSize());
        }
      });
      navhp.add(pageSizer);
      navhp.setCellVerticalAlignment(pageSizer,
          HasVerticalAlignment.ALIGN_MIDDLE);
      navhp.add(new Spacer(20, 1));
    }

    pager.setDisplay(cellTable);
    navhp.add(pager);
    navhp.setCellVerticalAlignment(pager, HasVerticalAlignment.ALIGN_MIDDLE);
    tophp.add(navhp);
    tophp.setCellHorizontalAlignment(navhp, HasHorizontalAlignment.ALIGN_RIGHT);
    rootVP.add(tophp);

    // center
    cellTable.setPageSize(pageSizer.getPageSize());
    cellTable.setWidth("100%");
    cellTable.setStyleName("ya-dataTable");
    rootVP.add(cellTable);

    // bottom
    pager2.setDisplay(cellTable);
    rootVP.add(pager2);
    rootVP.setCellHorizontalAlignment(pager2,
        HasHorizontalAlignment.ALIGN_RIGHT);

    rootVP.setWidth("100%");
  }

  @Override
  public void onItemListEvent(ItemListEvent event) {
    if (event.getListCache() != null) {
      String eventName = event.getListCache().getClass().getName();
      String objName = listCache.getClass().getName();
      if (objName != eventName)
        return;
      log.info("onDataReady: ItemListEvent caught: " + eventName);
      log.info("onDataReady: rendering data");
      cellTable.setRowData(0, listCache.getList());
      if (listCache.isFullyLoaded())
        cellTable.setRowCount(listCache.getList().size());
    }
  }

  private class MySimplePager extends SimplePager {
    public void onRangeOrRowCountChanged() {
      if (!listCache.isFullyLoaded() && !hasPage(getPage() + 1)) {
        log.info("populate: not enough data; calling listCache.fetchNext()");
        listCache.fetchNext();
        return;
      }

      super.onRangeOrRowCountChanged();
      cellTable.setRowData(0, listCache.getList());
    }
  }

  public CellTable<ItemDTO> getCellTable() {
    return cellTable;
  }

  /**
   * Adds button
   */
  public void addButton(String label, ClickHandler clickHandler) {
    Button button = new Button(label);
    button.addClickHandler(clickHandler);
    if (buttonBar == null)
      buttonBar = new ButtonBar();
    buttonBar.add(button);
  }

  /**
   * Displays or un-displays busy indicator
   */
  public void setBusy(boolean busy) {
    buttonBar.setBusy(busy);
  }

  /**
   * Displays message for 4 seconds
   * 
   * @param message
   *          message to be displayed
   */
  public void setMessage(String message) {
    buttonBar.setMessage(message, 4);
  }

  /**
   * Displays message
   * 
   * @param message
   *          message to be displayed
   * @param displaySeconds
   *          seconds for how long message is displayed
   */
  public void setMessage(String message, int displaySeconds) {
    buttonBar.setMessage(message, displaySeconds);
  }

  /**
   * Displays error message for 8 seconds
   * 
   * @param message
   *          error message to be displayed
   */
  public void setErrorMessage(String message) {
    buttonBar.setErrorMessage(message, 8);
  }

  /**
   * Displays error message
   * 
   * @param message
   *          error message to be displayed
   * @param displaySeconds
   *          seconds for how long error message is displayed
   */
  public void setErrorMessage(String message, int displaySeconds) {
    buttonBar.setErrorMessage(message, displaySeconds);
  }

  /**
   * Add a sort order option
   * 
   * @param number
   *          sort order number defined at the server
   * @param label
   *          label that appears on list box
   */
  public void addSortOrderOption(int number, String label) {
    if (sorter == null)
      sorter = new Sorter();
    sorter.addSortOrderOption(number, label);
  }

  public void setSortOrderOptionIndex(int sortOrderOptionIndex) {
    sorter.setSortOrderOptionIndex(sortOrderOptionIndex);
  }

  /**
   * Sets page size options to be displayed
   */
  public void setPageSizeOptions(int[] pageSizeOptions) {
    pageSizer.setPageSizeOptions(pageSizeOptions);
  }

  /**
   * Sets which page size is to be used from the list of options
   */
  public void setPageSizeOptionIndex(int pageSizeOptionIndex) {
    pageSizer.setPageSizeOptionIndex(pageSizeOptionIndex);
  }
}
